home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The CICA Windows Explosion!
/
The CICA Windows Explosion! - Disc 2.iso
/
nt
/
lkbackup.zip
/
tape.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-10-23
|
79KB
|
2,776 lines
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include <time.h>
#include <process.h>
#include <string.h>
#include <direct.h>
#include <errno.h>
/* these are the tape functions for my dat drive */
struct _TAPE_SET_MEDIA_PARAMETERS tparms;
#define max_save_sets 50
#define save_sets_per_block 10
#define blocks_per_header 5
#define bsize1 4096
const int blocksize = bsize1;
DWORD buffersize = bsize1;
const int headersize = 2048;
char saveset_buffer[2049];
BOOLEAN debug = FALSE;
int save_sets_on_tape = 0;
static char backup_version[13] = "LGKBACKUP1.0\0";
unsigned int total_original_size;
unsigned int total_backup_size;
int current_tape_block_number = 0;
BOOLEAN compress = FALSE;
int filescompressed = 0;
int filesuncompressed = 0;
DWORD start_time;
typedef struct savesettag {
char filename[300];
unsigned int filesize; /* suports 4 gif */
unsigned int starting_datablock_number;
} SAVESET_HEADER;
SAVESET_HEADER my_saveset_header;
/* 11 per buffer use 4 buffers */
typedef struct tapeheadertag {
char saveset_name[18];
unsigned int original_size;
unsigned int compressed_size;
char date[9];
} TAPE_HEADER;
TAPE_HEADER my_tape_header;
typedef struct rawtag {
char backupversion[13];
TAPE_HEADER header[max_save_sets];
} RAW_TAPE_HEADERT;
/* 15 save sets means we only need the first 512 byte block
since each reacord needs 32 bytes plus the first 12 = 502 total */
RAW_TAPE_HEADERT raw_tape_header;
typedef struct indexrectag {
int original_size;
int compressed_size;
char fname[351];
int start_block;
char date[9];
} INDEX_REC_TYPE;
const int header_size = sizeof(raw_tape_header);
FILE *TempIndexFile;
char TempIndexFileName[MAX_PATH];
BOOLEAN tempindexfileopen = FALSE;
HANDLE hTape; /* handle to tape device */
DWORD dwBytesRead, dwBytesWritten, dwPos;
BOOLEAN rdflag, wrflag;
BOOLEAN tape_opened = FALSE;
char todays_date[9];
unsigned int total_bytes_read = 0;
BOOLEAN quiet_mode = FALSE;
BOOLEAN set_mark_positioning = FALSE;
BOOLEAN reading_header = FALSE;
int filesskipped = 0;
#define severe 1
#define warning 0
/* ------------------------------------------------------------------------------------ */
/* beginning of functions */
/* ------------------------------------------------------------------------------------------- */
/* recursive wild card search routine */
BOOLEAN wild_match(search_string,target)
char *search_string;
char *target;
{
char *new_target;
int lens = strlen(search_string);
int lent = strlen(target);
BOOLEAN rvalue = FALSE;
/* handle terminating cases first */
if (lens == 1) /* last char of search string */
{
if (strncmp(search_string,"*",1) == 0)
{
/* is a wild card * */
return(TRUE);
}
else if ((strncmp(search_string,"?",1) == 0) && (lent == 1))
{
/* is a wild card ? */
return(TRUE);
}
else /* other char only matches if lent is also 1 and they match */
{
if ((lent == 1) && (strncmp(search_string,target,1) == 0))
return(TRUE);
else return(FALSE);
}
} /* lens = 1 */
else /* lens > 1 */
{
/* now check if chars is ? */
if (strncmp(search_string,"?",1) == 0)
{
/* if ? skip a char in both strings and recurse */
++search_string;
++target;
return(wild_match(search_string,target));
}
/* now check if char is * */
if (strncmp(search_string,"*",1) == 0)
{
/* find next char in search string */
do
{
++search_string;
/* here we also need to skip over ? as long as there is a char left
in the target */
} while (((strncmp(search_string,"*",1) == 0) ||
((strncmp(search_string,"?",1) == 0)) && (lent >= 1)));
/* if it is a ? recurse */
if ((strncmp(search_string,"?",1) == 0) && (lent == 0))
return(FALSE);
else /* other ok character no we need to find this character in the
target and recurse to try and resolve if the recursion fails
we need to try further on in the string do this until we either
suceed or the target string runs out and we fail */
{
rvalue = FALSE;
new_target = search_string;
do
{
new_target = strchr(target,new_target[0]);
if (new_target == NULL)
{
/* couldn't find character so we fail */
return(FALSE);
}
else
{
/* found the char so recurse with it */
rvalue = wild_match(search_string,new_target);
}
/* increment here */
target = new_target;
if (strlen(target) == 1)
return(FALSE);
else ++target;
} while (rvalue == FALSE);
/* if we get out of the inner loop without returning it means
we found a successfull match so we can return it */
return(rvalue);
} /* end of not * or ? */
} /* end of srch string was * */
else
{
/* srch string is another character so find it in target */
/* if next char in target is not the search string then we fail here
otherwise we need to increment both and recurse */
/* we also have a terminating case if if the length of the search string
is greater than one and the length of the remaining target string is only
one since the search string here is not a wildcard */
if (lent <= 1)
return(FALSE);
else if (strncmp(search_string,target,1) != 0)
return(FALSE);
else
{ /* they are equal so recurse through remainder of the string */
++search_string;
++target;
return(wild_match(search_string,target));
}
} /* end search string is regular character case */
} /* end len of srch string > 1 */
} /* end of routine */
/* -------------------------------------------------------------------------------------- */
void store_start_time()
{
start_time = GetTickCount();
}
/* ----------------------------------------------------------------------------------------- */
void close_tape()
{
CloseHandle(hTape);
if (debug)
{
printf("TapeIO:--> Closed Tape Drive\n\n");
fflush(stdout);
}
tape_opened = FALSE;
}
/* ------------------------------------------------------------------------------------------- */
void terminate_program()
{
if (tape_opened)
close_tape();
exit(1);
}
/* ------------------------------------------------------------------------------------ */
/* routine to report an error and terminat if severe */
void report_error(text,rvalue,severity)
char text[20];
DWORD rvalue;
int severity;
{
printf("TapeIO: --> Error %s :",text);
if (rvalue > 0)
printf(" error code returned = %ld ",rvalue);
printf(" Severity = %d \n",severity);
fflush(stdout);
if (severity > 0)
terminate_program();
}
/* --------------------------------------------------------------------------------------- */
/*
* After a file/link/symlink/dir creation has failed, see if
* it's because some required directory was not present, and if
* so, create all required dirs.
*/
int
make_dirs (pathname)
char *pathname;
{
char *p; /* Points into path */
int madeone = 0; /* Did we do anything yet? */
int save_errno = errno; /* Remember caller's errno */
int check;
// if (errno != ENOENT)
// return 0; /* Not our problem */
for (p = strchr (pathname, '\\'); p != NULL; p = strchr (p + 1, '\\'))
{
/* Avoid mkdir of empty string, if leading or double '/' */
if (p == pathname || p[-1] == '/')
continue;
/* Avoid mkdir where last part of path is '.' */
if (p[-1] == '.' && (p == pathname + 1 || p[-2] == '/'))
continue;
*p = 0; /* Truncate the path there */
check = _mkdir (pathname); /* Try to create it as a dir */
if (check == 0)
{
if (debug)
{
printf("made directory %s \n",pathname);
fflush(stdout);
}
madeone++; /* Remember if we made one */
*p = '/';
continue;
}
*p = '/';
if (errno == EEXIST) /* Directory already exists */
continue;
/*
* Some other error in the mkdir. We return to the caller.
*/
break;
}
errno = save_errno; /* Restore caller's errno */
return madeone; /* Tell them to retry if we made one */
}
/* --------------------------------------------------------------------------------------- */
HANDLE open_file_for_write(filename)
char filename[360];
{
HANDLE hFile;
int dirsmade;
hFile = CreateFile(filename,GENERIC_WRITE,FILE_SHARE_READ,(LPSECURITY_ATTRIBUTES)NULL,
CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS,(HANDLE)NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
/* if we fail here assume it is because the path is not there and call our function to
create directories along the path */
/* if it fails after this we are out of luck */
if (debug)
{
printf("create file %s failed calling make dirs to create any missing directories \n",
filename);
fflush(stdout);
}
dirsmade = make_dirs(filename);
/* now try again to open it */
hFile = CreateFile(filename,GENERIC_WRITE,FILE_SHARE_READ,(LPSECURITY_ATTRIBUTES)NULL,
CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS,(HANDLE)NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
printf("TapeIO:--> Error Could not create file %s num dirs created = %d\n",
filename,dirsmade);
report_error(" ",0,severe); /* process error */
}
else {
if (debug)
{
printf("TapeIO:-->Created file %s \n",filename);
fflush(stdout);
}
return hFile;
}
} /* end of first create failed */
else {
if (debug)
{
printf("TapeIO:-->Created file %s \n",filename);
fflush(stdout);
}
return hFile;
}
}
/* ------------------------------------------------------------------------------------ */
int compress_file(filename,temppath)
char filename[];
char *temppath;
{
char TempFileName[30];
char cmd[200];
DWORD lcopied = 0;
int rvalue = 0;
char *nameloc;
/* get the temp path */
/* append the temp filename and call gzip to execute and write the temp file name */
/* pass back the compressed file and we will back that up and remove it */
lcopied = GetTempPath(100,temppath);
if (lcopied <= 0)
{
report_error(" Cannot retrieve temporary directory path \n",0,warning);
return(-1);
}
else
{
/* now create a temp name and concat path to name */
rvalue = GetTempFileName(temppath, /* dir. for temp. files */
"NEW", /* temp. filename prefix */
0, /* create unique name w/ sys. time */
(LPTSTR) TempFileName); /* buffer for name */
if (rvalue == 0)
{
report_error(" Getting temp file name for compression \n",GetLastError(),warning);
return(-1);
}
else
{
/* concat path to name */
/* we only need to name form the temp file as it appends \temp\ to it
and we already have the temppath */
nameloc = strrchr(TempFileName,'\\');
/* skip over slash */
++nameloc;
strcat(temppath,nameloc);
if (debug)
{
printf("temp file for compress = %s \n",temppath);
fflush(stdout);
}
/* now create command to run zip having output go to tempfile. */
strcpy(cmd, "gzip -c1n "); /* use "gzip -c" for zwrite */
strncat(cmd, filename, sizeof(cmd)-strlen(cmd));
strcat(cmd," > ");
strcat(cmd, temppath);
if (debug)
{
printf("command for gzip = %s \n",cmd);
fflush(stdout);
}
rvalue = system(cmd);
if (rvalue != 0)
{
report_error("Spawn call to execute compression failed ",rvalue,severe);
return(-1);
}
else return(0);
} /* ok temp name */
} /* ok temp path name */
}
/* ------------------------------------------------------------------------------------ */
int decompress_file(filename,temppath)
char filename[];
char temppath[];
{
char cmd[200];
int rvalue = 0;
HANDLE tHandle;
/* open the file to make sure it can be created or force creation of paths */
tHandle = open_file_for_write(filename);
CloseHandle(tHandle);
/* now create command to run zip having output go from tempfile to original file */
strcpy(cmd, "gzip -d < "); /* use "gzip -c" for zwrite */
strncat(cmd, temppath, sizeof(cmd)-strlen(cmd));
strcat(cmd," > ");
strcat(cmd, filename);
if (debug)
{
printf("command for gzip = %s \n",cmd);
fflush(stdout);
}
rvalue = system(cmd);
if (rvalue != 0)
{
report_error("Spawn call to execute decompression failed ",rvalue,severe);
return(-1);
}
else return(0);
}
/* ------------------------------------------------------------------------------------ */
void write_setmarks(no_marks)
DWORD no_marks;
{
DWORD rvalue;
if (debug)
{
printf("Attempting to Write %d setmarks \n",no_marks);
fflush(stdout);
}
rvalue = WriteTapemark(hTape, TAPE_SETMARKS,no_marks,FALSE);
if (rvalue != NO_ERROR)
report_error(" Tape write setmarks error ",rvalue,severe);
}
/* ------------------------------------------------------------------------------------ */
void write_filemarks(no_marks)
DWORD no_marks;
{
DWORD rvalue;
if (set_mark_positioning)
{
write_setmarks(no_marks);
}
else
{
if (debug)
{
printf("Attempting to Write %d filemarks \n",no_marks);
fflush(stdout);
}
rvalue = WriteTapemark(hTape, TAPE_FILEMARKS,no_marks,FALSE);
if (rvalue != NO_ERROR)
report_error(" Tape write filemarks error ",rvalue,severe);
}
}
/* ------------------------------------------------------------------------------------ */
void fill_in_todays_date()
{
struct tm *newtime;
long ltime;
time( <ime );
/* Obtain Universal Coordinated Time: */
newtime = gmtime( <ime );
/* now fill in our date string */
sprintf(todays_date,"%2d-%2d-%2d",(newtime->tm_mon)+1,newtime->tm_mday,newtime->tm_year);
if (debug)
{
printf("filled in todays date with %s \n",todays_date);
fflush(stdout);
}
}
/* ------------------------------------------------------------------------------------ */
/* routine to open up the tape drive assumes only 1 tape drive for now */
void open_tape()
{
if (tape_opened == FALSE)
{
hTape = CreateFile(
"\\\\.\\TAPE0", /* name of tape device to open */
GENERIC_READ | GENERIC_WRITE, /* read-write access */
0, /* not used */
0, /* not used */
OPEN_EXISTING, /* required for tape devices */
0, /* not used */
NULL); /* not used */
if (hTape == NULL)
{
report_error("Opening tape device \n",0,1);
}
else
{
if (debug)
{ printf("TapeIO:--> Opened Tape drive.\n");
fflush(stdout);
}
tape_opened = TRUE;
}
}
}
/* ------------------------------------------------------------------------------------ */
/* function to set block size */
void set_block_size(bsize)
unsigned long bsize;
{
DWORD rvalue;
tparms.BlockSize = bsize;
rvalue = SetTapeParameters(hTape,SET_TAPE_MEDIA_INFORMATION,&tparms);
if (rvalue != NO_ERROR)
{
report_error("Setting tape media information ",rvalue,severe);
}
else
{
if (debug)
{
printf("TapeIO:--> Set tape media parameters i.e. blocksize to %ld\n",bsize);
fflush(stdout);
}
}
}
/* ------------------------------------------------------------------------------------ */
/* rewind the tape always wait for resute no immediate mode */
void rewind_tape()
{
DWORD rvalue;
rvalue = PrepareTape(hTape,TAPE_LOAD,FALSE);
if (rvalue != NO_ERROR)
{
report_error("rewinding tape ",rvalue,1);
}
else
{
current_tape_block_number = 0;
if (debug)
{
printf("TapeIO:-->Rewound Tape \n");
fflush(stdout);
}
}
}
/* ------------------------------------------------------------------------------------ */
void space_setmarks(no_marks)
DWORD no_marks;
{
DWORD rvalue;
DWORD status;
DWORD rvalue2;
if (debug)
{
printf("Attempting to Space %d setmarks\n",no_marks);
fflush(stdout);
}
rvalue = SetTapePosition(hTape,TAPE_SPACE_SETMARKS,0,no_marks,0,FALSE);
if (rvalue != NO_ERROR)
{
rvalue2 = GetLastError();
status = GetTapeStatus(hTape);
printf(" Tape positioning by setmarks error rvalue = %d tape status =%d getlsterror = %d\n",
rvalue,status,rvalue2);
fflush(stdout);
report_error(" ",0,severe);
}
}
/* ------------------------------------------------------------------------------------ */
void space_filemarks(no_marks)
DWORD no_marks;
{
DWORD rvalue;
DWORD status;
DWORD rvalue2;
if (set_mark_positioning)
{
space_setmarks(no_marks);
}
else {
if (debug)
{
printf("Attempting to Space %d file marks\n",no_marks);
fflush(stdout);
}
rvalue = SetTapePosition(hTape,TAPE_SPACE_FILEMARKS,0,no_marks,0,FALSE);
if (rvalue != NO_ERROR)
{
rvalue2 = GetLastError();
status = GetTapeStatus(hTape);
printf(" Tape positioning by filemarks error rvalue = %d tape status =%d getlsterror = %d\n",
rvalue,status,rvalue2);
fflush(stdout);
report_error(" ",0,severe);
}
}
}
/* ---------------------------------------------------------------------------------- */
void read_tape_block(buff)
char *buff;
{
DWORD rdflag;
rdflag = ReadFile(hTape, (LPSTR) buff, buffersize, &dwBytesRead, NULL);
/* handle strange error case of not spacing over file mark correctly if on
top of on assume it didn't space write and space over it */
if (rdflag != TRUE)
{
if ((reading_header) && (GetLastError() == ERROR_NO_DATA_DETECTED))
{ /* tape is not initialized */
printf("ERROR while trying to read the tape header information, \n");
printf(" no data was detected. It appears that this tape \n");
printf(" has not been initialized (LKBACKUP -i) \n");
fflush(stdout);
report_error("Error reading tape",rdflag,severe);
}
else
{
printf("error reading block getlasterror %d getstatus %d \n",
GetLastError(),GetTapeStatus(hTape));
fflush(stdout);
report_error("Error reading tape",0,severe);
}
}
else
{
++current_tape_block_number;
if (debug)
{
printf("TapeIO:--> Read %ld characters from the tape \n",dwBytesRead);
fflush(stdout);
}
}
}
/* ------------------------------------------------------------------------------------ */
void write_tape_block(buff)
char buff[];
{
DWORD wrflag;
DWORD dwBytesWritten;
wrflag = WriteFile(hTape, (LPSTR) buff, buffersize, &dwBytesWritten, NULL);
if (wrflag != TRUE)
{
report_error("Error writing tape",0,warning);
}
else
{
if (debug)
{
printf("TapeIO:--> Wrote %ld characters to the tape block = %d\n",
dwBytesWritten,current_tape_block_number);
fflush(stdout);
}
++current_tape_block_number;
}
}
/* ------------------------------------------------------------------------------------ */
DWORD read_file_block(lhfile,buff)
HANDLE lhfile;
char *buff;
{
DWORD rdflag;
DWORD dwBytesRead = 0;
rdflag = ReadFile(lhfile, (LPSTR) buff, buffersize, &dwBytesRead, NULL);
if (rdflag != TRUE)
{
report_error("Error reading file",0,warning);
}
else
{
if (debug)
{
printf("TapeIO:--> Read %ld characters from file \n",dwBytesRead);
fflush(stdout);
}
}
return(dwBytesRead);
}
/* ------------------------------------------------------------------------------------ */
DWORD write_file_block(lhfile,buff,bytes)
HANDLE lhfile;
char *buff;
int bytes;
{
DWORD dwBytesWritten = 0;
DWORD wrflag;
wrflag = WriteFile(lhfile, (LPSTR) buff, (DWORD)bytes, &dwBytesWritten, NULL);
if (wrflag != TRUE)
{
report_error("Error writing file",0,warning);
}
else
{
if (debug)
{
printf("TapeIO:--> Wrote %ld characters to file \n",dwBytesWritten);
fflush(stdout);
}
}
return(dwBytesWritten);
}
/* ------------------------------------------------------------------------------------ */
void dump_header_element(element_number)
int element_number;
{
if (strncmp(raw_tape_header.header[element_number].saveset_name,"EMPTY001_____",13) != 0)
{ /* ok not empty */
printf("%-8d",element_number);
printf("%16s",raw_tape_header.header[element_number].saveset_name);
printf("%13d %15d %8s\n",
raw_tape_header.header[element_number].original_size,
raw_tape_header.header[element_number].compressed_size,
raw_tape_header.header[element_number].date);
fflush(stdout);
}
}
/* ------------------------------------------------------------------------------------ */
void space_end_of_data()
{
DWORD rvalue;
if (debug)
{
printf("Attempting to Space to end of data \n");
fflush(stdout);
}
rvalue = SetTapePosition(hTape,TAPE_SPACE_END_OF_DATA,0,0,0,FALSE);
if (rvalue != NO_ERROR)
{
printf(" Tape positioning to end of data error rvalue = %d \n",rvalue);
fflush(stdout);
report_error(" ",rvalue,severe);
}
}
/* ----------------------------------------------------------------------------------------- */
void read_tape_index()
{
char block[bsize1];
int offset = 0;
int element_number = 0;
int end_element_number = 0;
int block_number = 0;
open_tape();
set_block_size(blocksize);
rewind_tape();
save_sets_on_tape = 0;
reading_header = TRUE;
/* retrive the tape id first */
read_tape_block(block);
reading_header = FALSE;
if (strncmp(block,backup_version,12) != 0)
{
/* tape is foreign format */
printf("Warning tape is foreign in format.\n");
printf("You must initialize it first with LKBACKUP -i\n");
fflush(stdout);
rewind_tape();
close_tape();
exit(1);
}
/* now get to the tape index */
space_end_of_data();
/* now go back one filemark to get to the beginning of the index */
space_filemarks(-1);
space_filemarks(1);
/* retrieve all blocks of the tape index */
current_tape_block_number = 0;
for (block_number = 0; block_number < blocks_per_header; block_number++)
{
read_tape_block(block);
offset = 0;
if (debug)
{
printf("Retrieved block %d %4096s \n",block_number,block);
fflush(stdout);
}
element_number = (block_number * save_sets_per_block);
end_element_number = element_number + save_sets_per_block;
do
{
sscanf(block + offset,"%16s",raw_tape_header.header[element_number].saveset_name);
offset = offset + 16;
sscanf(block + offset,"%10ud",&raw_tape_header.header[element_number].original_size);
offset=offset+10;
sscanf(block + offset,"%10ud",&raw_tape_header.header[element_number].compressed_size);
offset=offset+12;
sscanf(block + offset,"%8s",&raw_tape_header.header[element_number].date);
offset=offset+8;
if (debug)
{
printf("Current offset = %d \n",offset);
dump_header_element(element_number);
}
++element_number;
} while (element_number < end_element_number);
} /* end for all blocks */
rewind_tape();
}
/* ------------------------------------------------------------------------------------ */
void write_tape_id()
{
char block[bsize1];
int offset;
open_tape();
set_block_size(blocksize);
rewind_tape();
/* fill in backup version and all blocks info */
offset = sprintf(block,"%12s %8s\0",backup_version,todays_date);
write_tape_block(block); /* force data to be written */
write_filemarks(1);
}
/* ------------------------------------------------------------------------------------- */
void write_tape_index()
{
char block[bsize1];
int element_number = 0;
int end_element_number = 0;
int offset = 0;
int block_number = 0;
open_tape();
set_block_size(blocksize);
/* space to end of tape data */
rewind_tape();
space_end_of_data();
current_tape_block_number = 0;
for (block_number = 0; block_number < blocks_per_header; block_number++)
{
offset = 0;
for (element_number = (block_number * save_sets_per_block); element_number < (save_sets_per_block * (block_number + 1)); element_number++)
{
offset = offset + sprintf(block + offset,"%16s%10u %10u %8s",
raw_tape_header.header[element_number].saveset_name,
raw_tape_header.header[element_number].original_size,
raw_tape_header.header[element_number].compressed_size,
raw_tape_header.header[element_number].date);
}
if (debug)
printf("TapeIO:--> character count in buffer = %d\n",offset);
write_tape_block(block);
if (debug)
{
printf("wrote block %d %4096s \n",block_number,block);
fflush(stdout);
}
} /* end for loop */
/* write the file mark after the index */
rewind_tape();
}
/* ----------------------------------------------------------------------------- */
void fill_in_header_element(name,osize,csize,date,element_number)
char name[18];
unsigned int osize;
unsigned int csize;
char date[9];
int element_number;
{
strncpy(raw_tape_header.header[element_number].saveset_name,name,16);
raw_tape_header.header[element_number].original_size = osize;
raw_tape_header.header[element_number].compressed_size = csize;
strncpy(raw_tape_header.header[element_number].date,date,8);
raw_tape_header.header[element_number].date[8] = '\0';
}
/* ----------------------------------------------------------------------------------------- */
void clear_header()
{
int element_number;
for (element_number = 0; element_number< max_save_sets; element_number++)
fill_in_header_element("EMPTY001______________________",0,0,"00-00-00",element_number);
}
/* ------------------------------------------------------------------------------------------- */
void initialize_tape()
{
if (debug)
{
printf("TapeIO:--> Initializing Tape.\n");
fflush(stdout);
}
open_tape();
rewind_tape();
write_tape_id();
clear_header();
write_tape_index();
}
/* ------------------------------------------------------------------------------------------- */
void catalog_tape(no_good_backups)
char *no_good_backups;
{
int no_backups;
int rvalue;
int element_number;
char current_name[40];
char current_number[4];
rvalue = sscanf(no_good_backups,"%d",&no_backups);
if (rvalue == 0)
{
printf("Error %s is not a legal integer value for the number of good backups on the tape \n",
no_good_backups);
fflush(stdout);
report_error(" ",0,severe);
}
/* check for legal number */
if ((no_backups < 1) || (no_backups > max_save_sets))
{
printf("Error %d is not a legal integer value for the number of good backups on the tape \n",
no_backups);
fflush(stdout);
report_error(" ",0,severe);
}
/* otherwise do it */
/* fill in the correct number in the header */
clear_header();
for (element_number = 0; element_number < no_backups; element_number++)
{
strcpy(current_name,"saveset");
sprintf(current_number,"%d",element_number+1);
strcat(current_name,current_number);
while (strlen(current_name) < 30)
strcat(current_name," ");
if (debug)
{
printf("Filling in header with %s for saveset name len = %d \n",current_name,
strlen(current_name));
fflush(stdout);
}
fill_in_header_element(current_name,0,0,"00-00-00",element_number);
} /* end of loop */
/* now space to end of data and write out the index file again */
if (!quiet_mode)
{
printf("Attempting to restore the tape index\n");
fflush(stdout);
}
if (debug)
{
printf("TapeIO:--> Initializing Tape.\n");
fflush(stdout);
}
write_tape_index();
}
/* ------------------------------------------------------------------------------------ */
void erase_tape(secure)
BOOLEAN secure;
{
DWORD rvalue;
open_tape();
rewind_tape();
current_tape_block_number = 0;
if (secure)
rvalue = EraseTape(hTape,TAPE_ERASE_LONG,FALSE);
else rvalue = EraseTape(hTape,TAPE_ERASE_SHORT,FALSE);
if (rvalue != NO_ERROR)
{
report_error("Erasing tape ",rvalue,severe);
}
else
{
if (debug)
{
printf("TapeIO:-->Erased Tape");
if (secure)
printf(" Secure/long \n");
else printf(" Short \n");
fflush(stdout);
}
}
}
/* ------------------------------------------------------------------------------------ */
HANDLE open_file_for_read(filename,doing_backup_restore)
char filename[200];
BOOLEAN doing_backup_restore;
{
HANDLE hFile;
hFile = CreateFile(filename,GENERIC_READ,FILE_SHARE_READ,(LPSECURITY_ATTRIBUTES)NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN | FILE_FLAG_BACKUP_SEMANTICS,(HANDLE)NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
printf("TapeIO:--> Error Could not open file %s\n",filename);
fflush(stdout);
if (doing_backup_restore)
{
return(NULL);
}
else
report_error(" ",0,severe); /* process error */
}
else {
if (debug)
{
printf("TapeIO:-->Opened file %s \n",filename);
fflush(stdout);
}
return hFile;
}
}
/* --------------------------------------------------------------------------------------- */
void open_index_file()
{
DWORD lcopied = 0;
int rvalue = 0;
char TempName[40];
char *nameloc;
if (!tempindexfileopen)
{
lcopied = GetTempPath(100,TempIndexFileName);
if (lcopied <= 0)
report_error(" Cannot retrieve temporary directory path \n",0,severe);
else
{
/* now create a temp name and concat path to name */
rvalue = GetTempFileName(TempIndexFileName, /* dir. for temp. files */
"NEW", /* temp. filename prefix */
0, /* create unique name w/ sys. time */
(LPTSTR) TempName); /* buffer for name */
if (rvalue == 0)
report_error(" Getting temp file name for index file \n",rvalue,severe);
else
{
/* concat path to name */
/* we only need to name form the temp file as it appends \temp\ to it
and we already have the temppath */
nameloc = strrchr(TempName,'\\');
/* skip over slash */
++nameloc;
strcat(TempIndexFileName,nameloc);
TempIndexFile = fopen(TempIndexFileName,"w");
if (TempIndexFile == NULL)
report_error(" Could not create temporary index file.",0,severe);
else
{
if (debug)
{
printf("created temp index file %s \n",TempIndexFileName);
fflush(stdout);
}
tempindexfileopen = TRUE;
}
} /* name ok */
} /* path ok */
} /* not already open */
}
/* --------------------------------------------------------------------------------------- */
void write_index_entry(fpath,size,compressed_size,date,start_block)
char fpath[512];
unsigned int size;
unsigned int compressed_size;
char date[9];
int start_block;
{
int compression_percent = (int)(100.00 * (1.000 - (float)((float)compressed_size/(float)size)));
if ((compressed_size == 0) && (size > 0))
compression_percent = 0;
if (!tempindexfileopen)
open_index_file();
/* write info to command line and then to index file */
if (!quiet_mode)
{
printf("%s %d %d (%d)%% %8s %d\n",
fpath,size,compressed_size,compression_percent,date,start_block);
}
fprintf(TempIndexFile,"%350s %10d %10d %8s %10d \n",
fpath,size,compressed_size,date,start_block);
fflush(stdout);
fflush(TempIndexFile);
}
/* --------------------------------------------------------------------------------------*/
void close_index_file()
{
if (tempindexfileopen)
{
fclose(TempIndexFile);
if (debug)
{
printf("closed temp index file \n");
fflush(stdout);
}
tempindexfileopen = FALSE;
}
}
/* --------------------------------------------------------------------------------------*/
void backup_file(filename,size,attributes,indexfile)
char filename[];
DWORD size;
DWORD attributes;
BOOLEAN indexfile;
{
char lbuffer[bsize1];
HANDLE hFile;
LPTSTR ppszFilePart; /* address of filename in path */
DWORD rvalue;
FILETIME wtime;
BOOLEAN oktime;
DWORD dwAttrs;
unsigned int compress_size = 0;
char savepath[513];
int start_block = current_tape_block_number;
int ldwBytesRead = 0;
char compress_name[300];
BOOLEAN backing_up_compressed_file = FALSE;
unsigned short dostime;
unsigned short dosdate;
char file_date[9];
hFile = open_file_for_read(filename,TRUE);
/* now since file opened ok write out first buffer with file name and
size */
if (hFile == NULL) /* skip it since it couldn't be opened */
{
++filesskipped;
printf("Warning skipping file %s which could not be opened. \n",filename);
fflush(stdout);
}
else
{
if (debug)
{
printf("TapeIO:--> Backing up %s size is %ld \n",filename,size);
fflush(stdout);
}
/* write full path to file */
/* but erase first 3 chars ie i:\ so that restore is not drive specific */
rvalue = GetFullPathName((LPCSTR)filename,buffersize,(LPTSTR)lbuffer,&ppszFilePart);
if (rvalue == 0)
{
CloseHandle(hFile);
report_error(" Path + file name longer than max buffer size (512)\n",rvalue,severe);
}
lbuffer[0] = ' ';
lbuffer[1] = ' ';
lbuffer[2] = ' ';
strcpy(savepath,lbuffer);
if (debug)
{
printf("TapeIO:--> Backing up %s size is %ld \n",lbuffer,size);
fflush(stdout);
}
/* (*ctime).dwLowDateTime = 0;
(*atime).dwLowDateTime = 0;
(*wtime).dwLowDateTime = 0;
(*ctime).dwHighDateTime = 0;
(*atime).dwHighDateTime = 0;
(*wtime).dwHighDateTime = 0;
*/
/* now write file date/time and attributes */
oktime = GetFileTime(hFile,NULL,NULL,&wtime);
if (!oktime)
report_error(" Couldn't retrieve file time \n",0,warning);
/* get attr string */
/* get the files attributes and return true if it is a directory */
dwAttrs = GetFileAttributes(filename);
/* the the other dates when tried to accessed report an access violation if not on NTFS */
sprintf(lbuffer + rvalue," %d %d %d %d",size,attributes,
wtime.dwLowDateTime,wtime.dwHighDateTime);
write_tape_block(lbuffer);
if (debug)
{
printf("wrote block for file header %2048s \n",lbuffer);
fflush(stdout);
}
if ((compress) && (!indexfile)) /* do not compress the index file */
{
/* close the file handle */
CloseHandle(hFile);
compress_size = 0;
rvalue = compress_file(filename,&compress_name);
if (rvalue == 0)
{
/* file was compressed ok so close the file stream reopen with compressed file */
CloseHandle(hFile);
hFile = open_file_for_read(compress_name,FALSE);
backing_up_compressed_file = TRUE;
}
}
/* if compression failed then default to uncompressed file */
/* backup the file pointed to by hfile either compressed if worked or uncompressed otherwise */
do {
dwBytesRead = read_file_block(hFile,lbuffer);
if (dwBytesRead > 0)
{
if (debug)
{
printf("TapeIO:-->Attempting to write the buff to tape\n");
fflush(stdout);
}
write_tape_block(lbuffer);
if (backing_up_compressed_file)
compress_size = compress_size + dwBytesRead;
} /* bytes > 0 */
} while (dwBytesRead == buffersize);
/* close the file handle */
CloseHandle(hFile);
/* delete temp file if we have compression */
if (backing_up_compressed_file)
{
DeleteFile(compress_name);
++filescompressed;
total_backup_size = total_backup_size + compress_size;
}
else {
++filesuncompressed;
total_backup_size = total_backup_size + size;
}
/* for now use todays date later fill in with file date */
if (!indexfile)
{
/* need to convert to file date for the index entry */
if (!FileTimeToDosDateTime(&wtime,&dosdate,&dostime))
{
printf("Warning couldn't convert file date to dos date using todays date \n");
fflush(stdout);
write_index_entry(savepath,size,compress_size,todays_date,start_block);
}
/* ok we got the date no set it into varibles and convert to string */
else
{
int nDay = dosdate & 0x1f;
int nMonth = (dosdate >> 5) & 0x0f;
int nYear = (dosdate >> 9) + 80;
/* now convert to string */
sprintf(file_date,"%02d-%02d-%02d",nMonth,nDay,nYear);
write_index_entry(savepath,size,compress_size,file_date,start_block);
}
}
total_original_size = total_original_size + size;
} /* skip file */
}
/* ------------------------------------------------------------------------------------- */
void set_file_info(filename,lowtime,hightime,lattrs)
char *filename;
DWORD lowtime;
DWORD hightime;
DWORD lattrs;
{
FILETIME local_file_time;
HANDLE readHandle;
/* attempt to set date and file attributes */
if (lattrs != 0)
{
if (debug)
{
printf("Attempting to set file attributes to %d \n",lattrs);
fflush(stdout);
}
if (!SetFileAttributes(filename,lattrs))
{
printf("Warning couldn't set file %s attributes to %s during restore \n",filename,lattrs);
fflush(stdout);
}
}
/* now fill in a wtime struct and attempt to reset the time */
local_file_time.dwLowDateTime = lowtime;
local_file_time.dwHighDateTime = hightime;
readHandle = open_file_for_read(filename,TRUE);
if (!SetFileTime(readHandle,NULL,NULL,&local_file_time))
{
printf("Warning couldn't set file last write time for %s error = %d \n",
filename,GetLastError());
fflush(stdout);
}
CloseHandle(readHandle);
}
/* --------------------------------------------------------------------------------------*/
void restore_file(filename,size,csize,isindexfile)
char *filename;
int size;
int csize;
BOOLEAN isindexfile;
/* return the restored file name */
/* if it is the index file create it as orinally but append the temp drive to it */
{
char temppath[400];
BOOLEAN compressed = FALSE;
char lbuffer[bsize1];
HANDLE hFile;
int restore_size;
DWORD lcopied = 0;
unsigned int rvalue2;
char TempFileName[400];
char *nameloc;
BOOLEAN done;
int size_restored_so_far = 0;
char lname[400];
DWORD lowtime;
DWORD hightime;
DWORD lattrs;
int lsize;
if (csize > 0)
{
compressed = TRUE;
restore_size = csize;
/* create a temp file name/path to restore the file to */
} /* compress */
else
{
compressed = FALSE;
restore_size = size;
}
/* get the temp path for a compress restore or restore of the index file */
if (compressed || isindexfile)
{
lcopied = GetTempPath(100,temppath);
if (lcopied <= 0)
{
report_error(" Cannot retrieve temporary directory path \n",0,severe);
}
else
{
/* now create a temp name and concat path to name */
rvalue2 = GetTempFileName(temppath, /* dir. for temp. files */
"NEW", /* temp. filename prefix */
0, /* create unique name w/ sys. time */
(LPTSTR) TempFileName); /* buffer for name */
if (rvalue2 == 0)
{
report_error(" Getting temp file name for decompression \n",rvalue2,severe);
}
else
{
/* concat path to name */
/* we only need to name form the temp file as it appends \temp\ to it
and we already have the temppath */
nameloc = strrchr(TempFileName,'\\');
/* skip over slash */
++nameloc;
strcat(temppath,nameloc);
if (debug)
{
printf("temp file for decompress = %s \n",temppath);
fflush(stdout);
}
} /* name ok */
} /* path ok */
} /* for index or compressed file */
else
{
/* not compressed or index means regular file uncompressed to copy file name to temppath */
strcpy(temppath,filename);
}
if (debug)
{
printf("TapeIO:--> Restoring file about to read name block \n");
fflush(stdout);
}
read_tape_block(lbuffer);
if (debug)
{
printf("In restore file got name block number %s\n",lbuffer);
fflush(stdout);
}
if (isindexfile)
{
/* get the size out of the buffer */
sscanf(lbuffer,"%350s %10d",filename,&size);
restore_size = size; /* index file is not compressed */
if (debug)
{
printf("got name/size for index file name = %s size = %d \n",filename,size);
fflush(stdout);
}
}
/* check to make sure name in file matches restore name ignore check for index file */
else
{ /* must skip over first 3 characters in buffer that had e:\ etc. in it */
/* get times and attributes */
lsize = 0;
lattrs = 0;
lowtime = 0;
hightime = 0;
sscanf(lbuffer + 3,"%s %d %d %d %d",lname,&lsize,&lattrs,&lowtime,&hightime);
if (strncmp(filename,lname,strlen(filename)) != 0)
{
printf("Tape IO Error Name in buffer %350s does not match restore file name %s \n",
lbuffer,filename);
fflush(stdout);
report_error(" ",0,severe);
}
}
/* now restore the file wherever (to temppath) */
if (debug)
{
printf("attempting to open for write/restore: %s \n",temppath);
fflush(stdout);
}
hFile = open_file_for_write(temppath);
done = FALSE;
size_restored_so_far = 0;
/* restore the file pointed to by hfile */
do {
read_tape_block(lbuffer);
if (debug)
{
printf("TapeIO:-->Attempting to write the buff to file\n");
fflush(stdout);
}
if ((size_restored_so_far + blocksize) <= restore_size)
{
write_file_block(hFile,lbuffer,blocksize);
if ((size_restored_so_far + blocksize) == restore_size)
done = TRUE;
size_restored_so_far = size_restored_so_far + blocksize;
}
else /* write last partial block */
{
write_file_block(hFile,lbuffer,restore_size - size_restored_so_far);
if (debug)
{
printf("Writing out last partial block of %d characters \n",
restore_size - size_restored_so_far);
fflush(stdout);
}
done = TRUE;
size_restored_so_far = size_restored_so_far + (restore_size - size_restored_so_far);
} /* bytes > 0 */
} while (!done);
/* close the file handle */
CloseHandle(hFile);
/* now if the file was uncompressed or the index file
we are done otherwise if it was compressed we need to decompress it to the
original file */
if (!compressed)
{
if (!isindexfile)
set_file_info(filename,lowtime,hightime,lattrs);
if ((!quiet_mode) && (!isindexfile))
{
printf("Restored Uncompressed file %s \n",filename);
fflush(stdout);
}
++filesuncompressed;
total_bytes_read = total_bytes_read + size;
/* if index file copy name to ifle name */
if (isindexfile)
strcpy(filename,temppath);
}
else /* compressed */
{
/* now decompress it */
/* when decompressing the name somehow gets changes to / probably in the mkdir
routine can't find it so copy it, and copy back after decompress */
strcpy(lname,filename);
if (decompress_file(filename,temppath) == -1)
{
printf("Warning couldn't decompress file %s \n",lname);
printf("File NOT RESTORED \n");
printf("Leaving temp file %s for an attempt at manual decompression. \n",temppath);
fflush(stdout);
}
else
{
/* copy back */
strcpy(filename,lname);
set_file_info(filename,lowtime,hightime,lattrs);
if (!quiet_mode)
{
printf("Restored Compressed file %s\n",filename);
fflush(stdout);
}
++filescompressed;
total_bytes_read = total_bytes_read + csize;
DeleteFile(temppath);
}
}
}
/* -------------------------------------------------------------------------------------- */
void print_backup_stats()
{
DWORD total_time;
unsigned long int minutes;
unsigned long int backuprate;
total_time = GetTickCount() - start_time;
if (debug)
printf("total time = %d \n",total_time);
minutes = (int)(((float)total_time) / ((float)60000.0000));
/* 60 * 1000 which equal the number
of milliseconds in a minute */
backuprate = (int)(((float)total_original_size / (float)minutes) / (float)1024.000);
if (!quiet_mode)
{
printf("\n----------------------------------------------------------------\n");
printf("Files Backed Up --> %d \n",filescompressed+filesuncompressed);
printf(" No Compressed --> %d \n",filescompressed);
printf(" No UnCompressed --> %d \n",filesuncompressed);
printf("Files Skipped --> %d \n\n",filesskipped);
printf("Original Size --> %d \n",total_original_size);
printf("Size on Tape --> %d \n",total_backup_size);
printf("Compression Ratio --> (%2d%%)\n\n",
(int)(100.00 * (1.000 - (float)((float)total_backup_size/(float)total_original_size))));
printf("Backup Time (minutes) --> %d \n",minutes);
printf("Backup Rate K/minute --> %d \n",backuprate);
printf("\n----------------------------------------------------------------\n");
fflush(stdout);
}
}
/* --------------------------------------------------------------------------------------- */
void print_restore_stats()
{
DWORD total_time;
unsigned long int minutes;
unsigned long int restoreuprate;
total_time = GetTickCount() - start_time;
if (debug)
printf("total time = %d \n",total_time);
minutes = (int)(((float)total_time) / ((float)60000.0000));
/* 60 * 1000 which equal the number
of milliseconds in a minute */
restoreuprate = (int)(((float)total_bytes_read / (float)minutes) / (float)1024.000);
if (!quiet_mode)
{
printf("\n----------------------------------------------------------------\n");
printf("Files Restored --> %d \n",filescompressed+filesuncompressed);
printf(" No Compressed --> %d \n",filescompressed);
printf(" No UnCompressed --> %d \n\n",filesuncompressed);
printf("Total Bytes Restored --> %d \n",total_bytes_read);
printf("Restore Time (minutes) --> %d \n",minutes);
printf("Restore Rate K/minute --> %d \n",restoreuprate);
printf("\n----------------------------------------------------------------\n");
fflush(stdout);
}
}
/* --------------------------------------------------------------------------------------- */
void write_directory_file()
{
int fsize;
fsize = ftell(TempIndexFile);
close_index_file();
/* size is not important for this file */
/*ignore drive letter on file */
/* we need the file size here otherwise it will not know how much to restore */
backup_file(TempIndexFileName,fsize,0,TRUE); /* indicate this is the directory file */
/* now delete the file */
DeleteFile(TempIndexFileName);
}
/* ------------------------------------------------------------------------------------------ */
void process_write_directory(SearchString,process_subdirs)
char *SearchString;
BOOLEAN process_subdirs;
/* if process subdirs set first go through entire directory then do it again and process subdirs */
{
WIN32_FIND_DATA FileData;
HANDLE hSearch;
BOOLEAN done = FALSE;
BOOLEAN rvalue;
BOOLEAN onefound = FALSE;
/* Start searching for files in the current directory. */
hSearch = FindFirstFile(SearchString, &FileData);
if (hSearch == INVALID_HANDLE_VALUE)
{
/* no files in search parameters */
if ((debug) && (!process_subdirs))
{
printf("TapeIO:--> Warning no files found in search parameter %s \n",SearchString);
fflush(stdout);
}
if (!process_subdirs)
{
FindClose(hSearch);
return; /* cannot do this directory */
}
}
else onefound = TRUE;
if (onefound)
{
/* get size and process file only gets here if handle opened ok */
/* skip directories */
if (!(FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
backup_file(FileData.cFileName,FileData.nFileSizeLow,FileData.dwFileAttributes,FileData,FALSE);
/* loop through remainder of files */
do {
rvalue = FindNextFile(hSearch,&FileData);
if ((rvalue == FALSE) && (GetLastError() == ERROR_NO_MORE_FILES))
{
done = TRUE;
FindClose(hSearch);
}
else
{
if (!(FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
backup_file(FileData.cFileName,FileData.nFileSizeLow,FileData.dwFileAttributes,FALSE);
}
} while (!done);
} /* onefound */
/* now if process subdirs set go through and stop at all subdirs and recurse */
if (process_subdirs)
{
done = FALSE;
/* Start searching for all subdirectories to recurse on */
hSearch = FindFirstFile("*", &FileData);
if (hSearch == INVALID_HANDLE_VALUE)
{
FindClose(hSearch);
return; /* cannot do this directory */
} /* no files */
/* now check if file is subdir if so process if it is not "." or ".." */
if ((strncmp(FileData.cFileName,".",1) != 0) &&
(strncmp(FileData.cFileName,"..",2) != 0))
{
/* ok is not bs names */
if (FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if (SetCurrentDirectory(FileData.cFileName) == FALSE)
{
printf("TapeIO:--> Warning Couldn't change directory to %s \n",FileData.cFileName);
fflush(stdout);
}
else {
process_write_directory(SearchString,process_subdirs);
/* set current directory back */
SetCurrentDirectory("..");
}
} /* is directory */
} /* is not . or .. */
/* when it returns recurse through remainder of subdirs */
do
{
rvalue = FindNextFile(hSearch,&FileData);
if ((rvalue == FALSE) && (GetLastError() == ERROR_NO_MORE_FILES))
{
done = TRUE;
FindClose(hSearch);
}
else
{
/* now check if file is subdir if so process if it is not "." or ".." */
if ((strncmp(FileData.cFileName,".",1) != 0) &&
(strncmp(FileData.cFileName,"..",2) != 0))
{
/* ok is not bs names */
/* instead of using getfileattrs dwFileAttributes */
if (FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
/* is a directory so set directory and recurse */
if (SetCurrentDirectory(FileData.cFileName) == FALSE)
{
printf("TapeIO:--> Warning Couldn't change directory to %s \n",FileData.cFileName);
fflush(stdout);
}
else {
process_write_directory(SearchString,process_subdirs);
SetCurrentDirectory("..");
}
} /* is directory */
} /* is not . or .. */
} /* else not last file */
} while (!done);
} /* process subdirs */
}
/* ------------------------------------------------------------------------------------ */
void space_sequential_filemarks(no_marks)
DWORD no_marks;
{
DWORD rvalue;
if (debug)
{
printf("Attempting to Space %d Seqential file marks\n",no_marks);
fflush(stdout);
}
rvalue = SetTapePosition(hTape,TAPE_SPACE_SEQUENTIAL_FMKS,0,no_marks,0,FALSE);
if (rvalue != NO_ERROR)
report_error(" Tape positioning by sequential filemarks error ",rvalue,severe);
}
/* ------------------------------------------------------------------------------------ */
void space_scsi_blocks(no_blocks)
DWORD no_blocks;
{
DWORD rvalue;
if (debug)
{
printf("Attempting to Space %d Scsi data blocks \n",no_blocks);
fflush(stdout);
}
rvalue = SetTapePosition(hTape,TAPE_SPACE_RELATIVE_BLOCKS,0,no_blocks,0,FALSE);
if (rvalue != NO_ERROR)
report_error(" Tape positioning by scsi (relative) block error ",rvalue,severe);
}
/* ---------------------------------------------------------------------------------- */
void eject_tape()
{
DWORD rvalue;
rvalue = PrepareTape(hTape,TAPE_UNLOAD,FALSE);
if (rvalue != NO_ERROR)
{
report_error("Ejecting tape ",rvalue,severe);
}
else
{
if (debug)
{
printf("TapeIO:-->Unloaded/Ejected Tape \n");
fflush(stdout);
}
}
}
/* ---------------------------------------------------------------------------------- */
void list_tape()
{
int element_number = 0;
read_tape_index();
printf("Number Saveset Name Original Size Compressed Size Date \n");
printf("__________________________________________________________________\n");
for (element_number = 0; element_number < max_save_sets; element_number++)
dump_header_element(element_number);
printf("\nListing Complete\n\n");
fflush(stdout);
}
/* ------------------------------------------------------------------------------------ */
int find_free_saveset_element()
{
BOOLEAN found = FALSE;
int number = 0;
int element_number = 0;
for (element_number = 0; element_number < max_save_sets; element_number++)
{
if (strncmp(raw_tape_header.header[element_number].saveset_name,"EMPTY001_____",13) == 0)
{
number = element_number;
found = TRUE;
break;
}
}
if (found)
return(number);
else return(-1);
}
/* ------------------------------------------------------------------------------------- */
BOOLEAN get_index_file_entry(indexrec)
INDEX_REC_TYPE *indexrec;
{
int lsize;
int csize;
int sblock;
char ldate[9];
char fname[351];
int rvalue;
rvalue = fscanf(TempIndexFile,"%350s %10d %10d %8s %10d \n",fname,&lsize,&csize,ldate,&sblock);
if (rvalue == 0)
report_error("Reading index file entry \n",0,severe);
if (rvalue == EOF)
{
if (debug)
{
printf("EOF of index file found \n");
fflush(stdout);
}
fclose(TempIndexFile);
return(FALSE);
}
if (debug)
{
printf("Successfully retrieved index entry %s %d %d %8s %d\n",fname,lsize,csize,ldate,sblock);
fflush(stdout);
}
/* fill in fields */
indexrec->original_size = lsize;
indexrec->compressed_size = csize;
strcpy(indexrec->fname,fname);
strcpy(indexrec->date,ldate);
indexrec->start_block = sblock;
if (debug)
{
printf("Successfully filled in index entry %s %d %d %8s %d\n",
indexrec->fname,
indexrec->original_size,
indexrec->compressed_size,
indexrec->date,
indexrec->start_block);
fflush(stdout);
}
return(TRUE);
}
/* -------------------------------------------------------------------------------------- */
void list_index_file(indexfilename2,savesetname2)
char *indexfilename2;
char *savesetname2;
{
INDEX_REC_TYPE indexrec;
BOOLEAN rvalue = FALSE;
/* print header */
printf("Saveset Listing for %s \n",savesetname2);
printf("Original Size Compressed Size Date Start Block Filename\n");
printf("__________________________________________________________________________\n");
/* loop through and get file entry and print out contents */
/* first open up the index file for reading */
TempIndexFile = fopen(indexfilename2,"r");
if (TempIndexFile == NULL)
report_error(" Could not open temporary index file.",0,severe);
else
{
if (debug)
{
printf("opened for read temp index file %s \n",indexfilename2);
fflush(stdout);
}
tempindexfileopen = TRUE;
}
do {
rvalue = get_index_file_entry(&indexrec);
if (rvalue)
{
printf("%10d %10d %8s %10d %-s\n",
indexrec.original_size,
indexrec.compressed_size,
indexrec.date,
indexrec.start_block,
indexrec.fname);
fflush(stdout);
}
} while (rvalue == TRUE);
printf("\nListing Complete\n\n");
fflush(stdout);
}
/* ------------------------------------------------------------------------------------ */
int find_saveset_element(saveset)
char saveset[18];
{
BOOLEAN found = FALSE;
int number = 0;
int element_number = 0;
int slen = strlen(saveset);
for (element_number = 0; element_number < max_save_sets; element_number++)
{
if (strncmp(raw_tape_header.header[element_number].saveset_name,saveset,slen) == 0)
{
number = element_number;
found = TRUE;
break;
}
}
if (found)
return(number);
else return(-1);
}
/* --------------------------------------------------------------------------------------*/
void list_saveset(saveset)
char *saveset[18];
{
int element_number;
char indexfilename[400];
read_tape_index();
rewind_tape();
element_number = find_saveset_element(saveset);
if (element_number < 0)
{
printf("Saveset %s Not found on the tape, use LKBACKUP -l for a listing. \n",saveset);
fflush(stdout);
close_tape();
report_error(" ",0,severe);
}
/* now that we found the saveset space to the directory listing and read it */
/* tape id 1
1 data 2 index 3 saveset 0
3 data 4 index 5 saveset 1
5 data 6 index 7 saveset 2
7 data 8 index 9 saveset 3
.
.
.
tape index [filemark]
etc. */
space_filemarks((element_number * 2) + 2);
/* now recreate the file and list it */
restore_file(indexfilename,0,0,TRUE);
list_index_file(indexfilename,saveset);
DeleteFile(indexfilename);
rewind_tape();
close_tape();
}
/* --------------------------------------------------------------------------------- */
void process_restore(indexfilename2,search_string)
char *indexfilename2;
char search_string[];
{
/* now go through each line in the index file and check if name matches */
int lsize;
int csize;
int sblock;
char ldate[9];
char fname[351];
int rvalue;
BOOLEAN eof_found = FALSE;
INDEX_REC_TYPE indexrec;
/* first open up the index file for reading */
TempIndexFile = fopen(indexfilename2,"r");
if (TempIndexFile == NULL)
report_error(" Could not open temporary index file.",0,severe);
else
{
if (debug)
{
printf("opened for read temp index file %s \n",indexfilename2);
fflush(stdout);
}
tempindexfileopen = TRUE;
}
do {
rvalue = fscanf(TempIndexFile,"%350s %10d %10d %8s %10d \n",fname,&lsize,&csize,ldate,&sblock);
if (rvalue == 0)
report_error("Reading index file entry \n",0,severe);
if (rvalue == EOF)
{
if (debug)
{
printf("EOF of index file found \n");
fflush(stdout);
}
fclose(TempIndexFile);
eof_found = TRUE;
}
else
{
if (debug)
{
printf("Successfully retrieved index entry %s %d %d %8s %d\n",fname,lsize,csize,ldate,sblock);
fflush(stdout);
}
/* fill in fields */
indexrec.original_size = lsize;
indexrec.compressed_size = csize;
strcpy(indexrec.fname,fname);
strcpy(indexrec.date,ldate);
indexrec.start_block = sblock;
if (debug)
{
printf("Successfully filled in index entry %s %d %d %8s %d\n",
indexrec.fname,
indexrec.original_size,
indexrec.compressed_size,
indexrec.date,
indexrec.start_block);
fflush(stdout);
}
/* now check for match */
if (wild_match(search_string,indexrec.fname))
{
if (debug)
{
printf("match found %s with %s \n",search_string,indexrec.fname);
printf("current block = %d need to be at block %d \n",current_tape_block_number,
indexrec.start_block);
fflush(stdout);
}
if (current_tape_block_number < indexrec.start_block)
{
if (debug)
{
printf("attempting to space forward %d blocks \n",
indexrec.start_block - current_tape_block_number);
fflush(stdout);
}
space_scsi_blocks(indexrec.start_block - current_tape_block_number);
current_tape_block_number = indexrec.start_block;
}
else if (current_tape_block_number > indexrec.start_block)
{
/* error condition */
printf("TapeIO --->: Error tape position of %d > start block of %d shouldn't happen \n",
current_tape_block_number,indexrec.start_block);
fflush(stdout);
report_error(" ",0,severe);
}
/* now restore the file */
restore_file(indexrec.fname,indexrec.original_size,indexrec.compressed_size,FALSE);
} /* end of ok match */
} /* eof not found */
} while (!eof_found);
}
/* --------------------------------------------------------------------------------------*/
void do_restore(saveset,search_string)
char saveset[18];
char search_string[];
{
int element_number;
char indexfilename[400];
store_start_time();
total_bytes_read = 0;
filescompressed = 0;
filesuncompressed = 0;
read_tape_index();
rewind_tape();
element_number = find_saveset_element(saveset);
if (element_number < 0)
{
printf("Saveset %s Not found on the tape, use LKBACKUP -l for a listing. \n",saveset);
fflush(stdout);
close_tape();
report_error(" ",0,severe);
}
/* now that we found the saveset space to the directory listing and read it */
/* tape id 1
1 data 2 index 3 saveset 0
3 data 4 index 5 saveset 1
5 data 6 index 7 saveset 2
7 data 8 index 9 saveset 3
.
.
.
tape index [filemark]
etc. */
space_filemarks((element_number * 2) + 2);
/* now recreate the file and list it */
restore_file(indexfilename,0,0,TRUE);
/* now position to the backup set */
rewind_tape();
space_filemarks((element_number * 2) + 1);
current_tape_block_number = 0;
/* now process the restore */
total_bytes_read = 0;
filescompressed = 0;
filesuncompressed = 0;
process_restore(indexfilename,search_string);
/* now finish up */
DeleteFile(indexfilename);
rewind_tape();
close_tape();
if ((filescompressed+filesuncompressed) <= 0)
{
printf("Warning no files in saveset %s found with search string %s \n",saveset,
search_string);
fflush(stdout);
}
else print_restore_stats();
}
/* ------------------------------------------------------------------------------------ */
void do_backup(saveset_name,search_string,do_subdirs)
char saveset_name[];
char search_string[];
BOOLEAN do_subdirs;
{
int free_element = 0;
int taken_element = 0;
read_tape_index();
rewind_tape();
free_element = find_free_saveset_element();
if (free_element < 0)
report_error("No room for any more savesets on tape, initialize it or switch tapes \n",0,severe);
taken_element = find_saveset_element(saveset_name);
if (taken_element >= 0)
{
printf("Error: Saveset %s Already exists on the tape... Try another name. \n",saveset_name);
fflush(stdout);
report_error(" ",0,severe);
}
else
{
store_start_time();
/* now space to the correct file mark and start writing the backup */
space_filemarks((free_element * 2) + 1 ); // 1 extra to get over header */
/* reset the current tape block number to be relative from the beginning of the
save set */
current_tape_block_number = 0;
/* this should put the tape ready to write the backup since there is two file marks
per backup 1 before the backup and 1 between the backup and its directory so the
directory can be retrieved quickly ie element 0 is filemark 0 element4 is file mark
8 */
/* now do the backup */
total_original_size = 0;
total_backup_size = 0;
filescompressed = 0;
filesuncompressed = 0;
process_write_directory(search_string,do_subdirs); /* also do subdirectories if set */
/* dont write marks if nothing was backed up */
if ((filescompressed + filesuncompressed) == 0)
{
printf("Warning no files found in search parameter %s \n",search_string);
fflush(stdout);
}
else
{
/* now write the file mark */
write_filemarks(1);
/* now write the directory file */
write_directory_file();
/* now write another file mark */
write_filemarks(1);
/* now fill in the total size/compressed size and rewind and rewrite header */
/* also print out status messages */
fill_in_header_element(saveset_name,total_original_size,total_backup_size,
todays_date,free_element);
/* now rewrite header */
write_tape_index();
}
/* now rewind tape */
rewind_tape();
close_tape();
print_backup_stats();
} /* is room for new saveset */
}
/* ------------------------------------------------------------------------------------ */
void disp_help()
{
printf(" USAGE for LKBACKUP Version 1.0 by L. Kahn 1993 \n");
printf("LKBACKUP [-d -q -c -s] -b saveset_name search_string [include_subdirs] \n");
printf("LKBACKUP [-d -q -c] -e [long_or_short] or LGKBACKUP -h or \n");
printf("LKBACKUP [-d -q -c -s] -i or\n");
printf("LKBACKUP [-d -q -c -s] -L saveset_name or\n");
printf("LKBACKUP [-d -q -c -s] -l or \n");
printf("LKBACKUP [-d -q -c -s] -r saveset_name search_string \n");
printf("LKBACKUP [-d -q -c -s] -C no_of_good_savesets\n");
printf("Where ... \n");
printf("-b = Backup using the search string starting from the current directory, \n");
printf(" including subdirs is optional and depedent on the value of \n");
printf(" include_subddirs (T or F) \n");
printf("-e = Erase tape where erasing long or short is optional. Default is short \n");
printf("-h = Display this HELP message \n");
printf("-i = Initialize tape (necessary before usage) \n");
printf("-l = List tape (i.e., name of all savesets)\n");
printf("-L = List the contents of a specific saveset \n");
printf("-r = Restore the saveset_name using the search_string\n");
printf("-C = Catalog tape (set index to say there are no_good_savesets) \n");
printf(" Should be used if for some reason a backup fails or power goes out\n");
printf(" during a backup. Rewrites the tape index, restores can then be \n");
printf(" performed but further backups may be unreliable.\n");
printf("-d = turn on debugging, -q = quiet_mode, -c = turn on compression -s use setmarks not filemarks");
}
/* ------------------------- main program */
void main(int argc,char *argv[])
{
int current_arg = 1;
BOOLEAN more_args = TRUE;
BOOLEAN done = FALSE;
BOOLEAN do_subdirs = FALSE;
fill_in_todays_date();
if ((argc < 2) || (argc > 8))
disp_help();
else
{
/* process arguments */
if (argv[current_arg][0] != '-')
disp_help();
else
do
{
/* get the first one and if it doesn't start with a - we have a problem */
switch (argv[current_arg][1])
{
case 'c':
compress = TRUE;
break;
case 'q':
quiet_mode = TRUE;
break;
case 'd':
debug = TRUE;
break;
case 'h':
disp_help();
done = TRUE;
break;
case 's':
set_mark_positioning = TRUE;
break;
case 'C':
if (argc < (current_arg + 2))
{
printf("ERROR: Number of good savesets needed for catalog procedure \n");
fflush(stdout);
}
else {
catalog_tape(argv[current_arg + 1]);
}
done = TRUE;
break;
case 'i':
initialize_tape();
done = TRUE;
break;
case 'l':
list_tape();
done = TRUE;
break;
case 'L':
if (argc < (current_arg + 2))
{
printf("ERROR: Saveset name needed for tape listing. Use LKBACKUP -h for help \n");
fflush(stdout);
}
else {
list_saveset(argv[current_arg + 1]);
}
done = TRUE;
break;
case 'e':
if (argc >= (current_arg + 2))
{
/* we have a short or long option so check it */
switch (argv[current_arg+1][0])
{
case 's':
erase_tape(FALSE);
done = TRUE;
break;
case 'l':
erase_tape(TRUE);
done = TRUE;
break;
default:
printf("ERROR: Legal options for erase are s for short erase or l for long erase \n");
printf("Use LKBACKUP -h for help \n");
fflush(stdout);
done = TRUE;
break;
}
if (done)
break;
} /* end have extra arg */
else erase_tape(FALSE);
done = TRUE;
break;
case 'b':
/* make sure we have enough parms */
if (argc < (current_arg+3))
{
printf("ERROR: The search_string and the saveset_name are required for a backup operation. \n");
printf("Use LKBACKUP -h for help \n");
fflush(stdout);
done = TRUE;
break;
}
/* check for include subdirs */
if (argc == (current_arg + 4))
{
switch (argv[current_arg+3][0])
{
case 't':
do_subdirs = TRUE;
break;
case 'f':
do_subdirs = FALSE;
break;
default:
printf("Error: The legal options for including subdirectories are t for f.\n");
printf("Use LKBACKUP -h for help \n");
fflush(stdout);
done = TRUE;
break;
}
} /* have optional parm */
if (done)
break;
/* if we get here do the backup */
if (debug)
{
printf("calling backup %s %s %d \n",argv[current_arg+1],
argv[current_arg+2],do_subdirs);
fflush(stdout);
}
do_backup(argv[current_arg+1],argv[current_arg+2],do_subdirs);
done = TRUE;
break;
case 'r':
/* make sure we have enough parms */
if (argc < (current_arg+3))
{
printf("ERROR: The search_string and the saveset_name are required for a restore operation. \n"); printf("Use LKBACKUP -h for help \n");
fflush(stdout);
done = TRUE;
break;
}
else
{
if (debug)
{
printf("Restore %s %s \n",argv[current_arg+1],argv[current_arg+2]);
fflush(stdout);
}
do_restore(argv[current_arg+1],argv[current_arg+2]);
done = TRUE;
break;
}
default:
printf("Illegal option %s \n",argv[current_arg]);
disp_help();
done = TRUE;
break;
} /* end of switch */
++current_arg;
if (current_arg > argc)
more_args = FALSE;
} while ((!done) && (more_args));
} /* end of ok case */
} /* end of main */